'use strict';

// 创建一个类，
const pkgDir = require('pkg-dir').sync;
const path = require('path')
const fse = require('fs-extra');
const pathExists = require('path-exists').sync;
const npminstall = require("npminstall")
const { isObject } = require("@cli-dev/utils")
const formatPath = require('@cli-dev/format-path')
const {getDefaultRegistry,getNpmLatestVersion} = require("@cli-dev/get-npm-info");
const log = require("@cli-dev/log")




class Package{
    constructor(options){
        if(!options ){
            throw new Error('Package类的options参数不能为空')
        }
        if(!isObject(options)){
            throw new Error('Package类的options参数必须为对象')
        }

        // package的目标路径
        this.targetPath = options.targetPath;
        // package的缓存路径
        this.storeDir = options.storeDir
        // package的name
        this.packageName= options.packageName
        // package的version
        this.packageVersion = options.packageVersion
        this.cacheFilePathPrefix = this.packageName.replace('/','_')
        log.verbose('options',options)
    }
    // 判断package是否存在
    async exists(){
      log.verbose('exists')
     
      if(this.storeDir){
        await this.prepare();
          // 如果缓存中有
          return pathExists(this.cacheFilePath)

      }else {
          return pathExists(this.targetPath)
      }
    }
  
    // 安装package
   async install() {
    log.verbose('install')
    await this.prepare();
    return npminstall({
      root: this.targetPath,
      storeDir: this.storeDir,
      registry: getDefaultRegistry(),
      pkgs: [{
        name: this.packageName,
        version: this.packageVersion,
      }],
    });
  }

    async prepare() {
        if (this.storeDir && !pathExists(this.storeDir)) {
          fse.mkdirpSync(this.storeDir);
        }
        if (this.packageVersion === 'latest') {
          this.packageVersion = await getNpmLatestVersion(this.packageName);
        }

        log.verbose('packageVersion', this.packageVersion)
      }
    get cacheFilePath(){
        return path.resolve(this.storeDir, `_${this.cacheFilePathPrefix}@${this.packageVersion}@${this.packageName}`)
    }

    getSpecificCacheFile(packageVersion){
        return path.resolve(this.storeDir, `_${this.cacheFilePathPrefix}@${packageVersion}@${this.packageName}`)
    }
    // 更新package
  async  update(){
        // 1.获取最新的npm模块版本号
        // const latestPackageVersion = await getNpmLatestVersion(this.packageName)
         const latestPackageVersion = await getNpmLatestVersion(this.packageName)
        // 2. 查询最新版本号对应的路径是否存在
        const latestFilePath = this.getSpecificCacheFile(latestPackageVersion)
          // 3.如果不存在，就安装最新的版本
          log.verbose('latestFilePath', latestPackageVersion)
        if(!pathExists(latestFilePath)){
            log.verbose('update',packageName)
            await npminstall({
                root: this.targetPath,
                storeDir: this.storeDir,
                registry: getDefaultRegistry(),
                pkgs:[
                    {
                        name: this.packageName,
                        version: latestPackageVersion
                    }
                ]
            })
            // 包更新之后，要把版本号一同更新
            this.packageVersion = latestPackageVersion;
        }else {
          this.packageVersion = latestPackageVersion;
        }

    }
    //获取本地入口文件的路径
    getRootFilepath(){
        /**
         * 1. 获取package.json所在的目录-pkg-dir
         * 2.读取package.json-require() js/json/node
         * 3.寻找找到main/lib的path
         * 4.路径兼容（macOs/windows)
         */
        function _getRootFile(targetPath){
            const dir = pkgDir(targetPath)
            // 1. 获取package.json所在的目录
            if(dir){
                const pkgFile = require(path.resolve(dir, 'package.json'))
                  // 找到main/lib
                if(pkgFile && pkgFile.main){
                    return formatPath(path.resolve(dir, pkgFile.main))
                }
            }
            return null
        }
        if(this.storeDir){
            // 如果有缓存路径
            return _getRootFile(this.cacheFilePath)
        }else {
            return _getRootFile(this.targetPath)
        }
    } 
    
}

module.exports = Package;
